package co.edu.uniandes.services;

import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;

import co.edu.uniandes.dto.Usuario;
import co.edu.uniandes.services.constantes.ConsultaConstantes;

/**
 * Se encarga de realizar el CRUD de usuario y adicionalmente de verificar la
 * autenticacion de un usuario frente al sistema
 * 
 * @author Diego Alejandro Olivera Rios <diegoalejo14@gmail.com>
 * 
 */
public class ServicioUsuario extends UnicastRemoteObject implements IServicioUsuario {

	/**
	 * Contructor
	 * @throws RemoteException
	 */
	public ServicioUsuario() throws RemoteException {
		super();
	}

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	/**
	 * Se encarga de insertar los datos de un usuario en BD
	 * 
	 * @param Usuario
	 *            Datos del usuario
	 * @throws Exception
	 *             En caso de que el usuario, el login, el password o el
	 *             tipoAdmin no hayan sido diligenciados. Adicionalmente se va a
	 *             lanzar una excepcion en caso de que se presenten problemas
	 *             con la base de datos
	 */
	public void insertar(Usuario usuario) throws Exception {
		PreparedStatement ps = null;
		
		try {
			if (usuario == null || usuario.getLogin() == null
					|| usuario.getPassword() == null) {
				throw new Exception(
						"No se puede guardar el usuario ya que tiene datos sin diligenciar");
			}
			Connection conexion = ConexionBD.getInstance().getConection();
			ps = conexion.prepareStatement(ConsultaConstantes.INSERT_USUARIO);
			ps.setString(1, usuario.getLogin());
			ps.setString(2, usuario.getPassword());
			ps.setInt(3, usuario.getTipoAdmin());

			ps.execute();
		} catch (Exception e) {
			throw e;
		} finally {
			if (ps != null && !ps.isClosed()) {
				ps.close();
			}

		}
	}

	/**
	 * Se encarga de obtener todos los usuarios que se encuentran en base de
	 * datos
	 * 
	 * @throws Exception
	 *             Se lanza cuando se presentan problemas con la conexion de BD
	 */
	public List<Usuario> consultar() throws Exception {
		
		List<Usuario> retorno = new ArrayList<Usuario>();
		PreparedStatement ps = null;
		ResultSet rs = null;
		try {
			Connection con = ConexionBD.getInstance().getConection();
			ps = con.prepareStatement(ConsultaConstantes.CONSULTA_USUARIO);
			rs = ps.executeQuery();
			Usuario usuario = null;
			while (rs.next()) {
				usuario = new Usuario();
				usuario.setId(rs.getInt("id"));
				usuario.setLogin(rs.getString("login"));
				usuario.setPassword(rs.getString("password"));
				usuario.setTipoAdmin(rs.getInt("tipoAdmin"));
				retorno.add(usuario);
			}
		} catch (Exception e) {
			throw e;
		} finally {
			if (rs != null && !rs.isClosed()) {
				rs.close();
			}
			if (ps != null && !ps.isClosed()) {
				ps.close();
			}
		}

		return retorno;
	}

	/**
	 * Se encarga de eliminar un usuario identificado con cierto id
	 * 
	 * @param id
	 *            Identificacion del usuario
	 * @throws Exception
	 *             Cuando la identificacion del usuario es nula o cuando se
	 *             presenta problemas con la BD
	 */
	@Override
	public void eliminar(Integer id) throws Exception {
		
		PreparedStatement ps = null;
		if (id == null) {
			throw new Exception(
					" La identificacion del usuario que se va a eliminar es nula");
		}
		try {
			Connection connection = ConexionBD.getInstance().getConection();
			ps = connection.prepareStatement(ConsultaConstantes.DELETE_USUARIO);
			ps.setInt(1, id);
			ps.execute();
		} catch (Exception e) {
			throw e;
		} finally {
			if (ps != null && !ps.isClosed()) {
				ps.close();
			}
		}
	}
	/**
	 * Se encarga de modificar los datos de un usuario en BD
	 * 
	 * @param Usuario
	 *            Datos del usuario
	 * @throws Exception
	 *             En caso de que el usuario, el login, el password o el
	 *             tipoAdmin no hayan sido diligenciados. Adicionalmente se va a
	 *             lanzar una excepcion en caso de que se presenten problemas
	 *             con la base de datos
	 */
	public void modificar(Usuario usuario) throws Exception {
		PreparedStatement ps = null;
		
		try {
			if (usuario == null || usuario.getLogin() == null
					|| usuario.getPassword() == null) {
				throw new Exception(
						"No se puede guardar el usuario ya que tiene datos sin diligenciar");
			}
			Connection conexion = ConexionBD.getInstance().getConection();
			ps = conexion.prepareStatement(ConsultaConstantes.UPDATE_USUARIO);
			ps.setString(1, usuario.getLogin());
			ps.setString(2, usuario.getPassword());
			ps.setInt(3, usuario.getTipoAdmin());
			ps.setInt(4, usuario.getId());

			ps.execute();
		} catch (Exception e) {
			throw e;
		} finally {
			if (ps != null && !ps.isClosed()) {
				ps.close();
			}

		}
		
	}
	/**
	 * Se encarga de verificar los datos de ingreso de un usuario a la
	 * aplicacion
	 * 
	 * @param Usuario
	 *            datos que se desean verificar contra el usuario
	 * @throws En
	 *             caso de que el usuario, el login, el password o el tipoAdmin
	 *             no hayan sido diligenciados. Adicionalmente se va a lanzar
	 *             una excepcion en caso de que se presenten problemas con la
	 *             base de datos
	 * @return Si se encuentra por lo menos un usuario con los datos ingresados
	 *         se retornara true, de lo contratrio se retornara false
	 */
	public Usuario autenticar(Usuario usuario) throws Exception {
		// Sentencia que va a ser utilizada para verificar la autenticacion de
		// un usuario
		
		PreparedStatement ps = null;
		ResultSet rs = null;
		try {
			if (usuario == null || usuario.getLogin() == null
					|| usuario.getPassword() == null
					|| usuario.getTipoAdmin() == 0) {
				throw new Exception("Existen datos sin ser ingresados");
			}
			Connection conexion = ConexionBD.getInstance().getConection();
			ps = conexion.prepareStatement(ConsultaConstantes.CONSULTA_USUARIO_POR_USUARIO);
			ps.setString(1, usuario.getLogin());
			ps.setString(2, usuario.getPassword());
			ps.setInt(3, usuario.getTipoAdmin());
			rs = ps.executeQuery();			
			// Se verifica que exista minimo un usuario con las condiciones
			// ingresadas
			if (rs.next()) {
				
				Usuario unUsuario = new Usuario();
				unUsuario.setId(rs.getInt("id"));
				unUsuario.setLogin(rs.getString("login"));
				unUsuario.setPassword(rs.getString("password"));
				unUsuario.setTipoAdmin(rs.getInt("tipoAdmin"));
				
				return unUsuario;
			}
			return null;
		} catch (Exception e) {
			throw e;
		} finally {
			if (rs != null && !rs.isClosed()) {
				rs.close();
			}
			if (ps != null && !ps.isClosed()) {
				ps.close();
			}
		}
	}
	
	

	
}
